#include <stdio.h>
#include <stdbool.h>
#define Size 10

//初始化函数：对操作对象的初始状态赋值
void InitBoard(char (*Board)[Size])
{
    for(int i = 0; i < Size; i++)
    {
        for(int j =0; j < Size; j++)
        {
            Board[i][j] = '-'; //每个位置初始化为-
        }
    }
}

//打印棋盘
void PrintBoard(char (*Board)[Size])
{
    printf("    ");
    for(int i = 0; i < Size; i++)
    {
        printf("%4d",i+1);
    }
    printf("\n");
    for(int i = 0; i < Size; i++)
    {
        printf("%4d",i+1);
        for(int j = 0; j < Size; j++)
          printf("%4c",Board[i][j]); //%4c：每个字符占4个字符的宽度

        printf("\n");
    }
}

//下棋函数
bool MakeMove(char(*Board)[Size],int row,int column,char player)
{
    // 非法位置
    if(row < 0 || row >= Size || column < 0 || column >= Size)
    {
        printf("非法的下棋位置，请重新输入!\n");
        return false;
    }
    //该位置已经有棋子了
    if(Board[row][column] != '-')
    {
        printf("该位置已经有棋子了，请重新选择位置!\n");
        return false;
    }
    Board[row][column] = player;
    return true;
}

//判断位置是否合法
bool IsValidPlace(char (*Board)[Size],int row,int column)
{
    if(row < 0 || row >= Size || column < 0 || column >= Size)
    {
        return false;
    }
    return true;
}

bool CheckIsWin(char (*Board)[Size],int row,int column,char player)
{
    //向量法
    int direction[4][2] = 
    {
        {1,0},
        {1,1},
        {0,1},
        {-1,1}
    };

    //遍历四个方向，数棋子数量
    for(int i = 0; i < 4; i++)
    {
        int count = 1;
        //下一个棋子的位置
        int drow = row + direction[i][0];
        int dcolumn = column + direction[i][1];
        //位置合法且是我自己的棋子
        while (IsValidPlace(Board,drow,dcolumn) && Board[drow][dcolumn] == player)
        {
            count++;
            if(count >= 5)
               return true;
            drow = drow + direction[i][0];
            dcolumn = dcolumn + direction[i][1];
        }
        //反方向继续找
        drow = row - direction[i][0];
        dcolumn = column - direction[i][1];
        while (IsValidPlace(Board,drow,dcolumn) && Board[drow][dcolumn] == player)
        {
            count++;
            if(count >= 5)
               return true;
            drow = drow - direction[i][0];
            dcolumn = dcolumn - direction[i][1];
        }

    }
    return false;

}

//判断是否构成n个一条线
bool CheckIsCount(char (*Board)[Size],int row,int column,char player,int number)
{
    //向量法
    int direction[4][2] = 
    {
        {1,0},
        {1,1},
        {0,1},
        {-1,1}
    };

    //遍历四个方向，数棋子数量
    for(int i = 0; i < 4; i++)
    {
        int count = 1;
        //下一个棋子的位置
        int drow = row + direction[i][0];
        int dcolumn = column + direction[i][1];
        //位置合法且是我自己的棋子
        while (IsValidPlace(Board,drow,dcolumn) && Board[drow][dcolumn] == player)
        {
            count++;
            if(count >= number)
               return true;
            drow = drow + direction[i][0];
            dcolumn = dcolumn + direction[i][1];
        }
        //反方向继续找
        drow = row - direction[i][0];
        dcolumn = column - direction[i][1];
        while (IsValidPlace(Board,drow,dcolumn) && Board[drow][dcolumn] == player)
        {
            count++;
            if(count >= number)
               return true;
            drow = drow - direction[i][0];
            dcolumn = dcolumn - direction[i][1];
        }

    }
    return false;

}

//判断平局
bool CheckIsDraw(char (*Board)[Size])
{
    for(int i = 0; i < Size; i++)
    {
        for(int j = 0; j < Size; j++)
        {
            if(Board[i][j] == '-')
            {
                return false;
            }
        }
    }
    return true;
}

void AIMakeMove(char (*Board)[Size],int row,int column) //玩家所下的位置
{
    //优先取胜策略
    for(int i = 0; i < Size; i++)
    {
        for(int j = 0; j < Size; j++)
        {
            if(Board[i][j] == '-')
            {
                Board[i][j] = 'o';
                if(CheckIsWin(Board,i,j,'o'))
                {
                    return ;
                }
                Board[i][j] = '-';
            }
        }
    }

    //阻止玩家获胜
    for(int k = 5; k >= 2; k--)
    {
        for(int i = 0; i < Size; i++)
     {
        for(int j = 0; j < Size; j++)
        {
            if(Board[i][j] == '-')
            {
                Board[i][j] == 'X';
                if(CheckIsCount(Board,i,j,'X',k))
                {
                    Board[i][j] = 'o';
                    return ;
                }
                Board[i][j] = '-';
            }
        }
     }
    }
    //阻止玩家四个
    //阻止玩家三个
    //阻止玩家两个
    
}

int main()
{
    char Board[Size][Size] = {0};
    InitBoard(Board);

    char player = 'X';
    int row = 0, column = 0;
    while (1)
    {
        PrintBoard(Board);
        int row = 0, column = 0;
        printf("请|%c|选手下棋：\n",player);

        if(player == 'X')
        {
            scanf("%d %d",&row,&column);
            if(MakeMove(Board,row-1,column-1,player) == false)
          {
            continue;
          }
        else
          {
            printf("AI正在下棋......\n");
            AIMakeMove(Board,row-1,column-1);
          }
        }

        if(CheckIsWin(Board,row-1,column-1,player) == true)
        {
            PrintBoard(Board);
            printf("恭喜|%c|选手获胜！\n",player);
            break;
        }
        if(CheckIsDraw(Board))
        {
            PrintBoard(Board);
            printf("平局！\n");
            break;
        }
        
        //换边
        player = (player == 'X')? 'O': 'X';
    }
    

    return 0;
}